package com.turing.pre.processor.file.processor;

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import com.turing.pre.processor.config.ConfigKey;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.*;

/**
 * 功能描述  wps转PDF
 *
 * @param * @param null
 * @author WN
 * @date 2020/9/7
 * @return
 */
@Slf4j
public class FileToPdf {
    // 文档格式转换组件
    public static final String WORDSERVER_STRING = "KWPS.Application";
    // 幻灯片格式转换组件
    public static final String PPTSERVER_STRING = "KWPP.Application";
    // 表格格式转换组件
    public static final String EXECLSERVER_STRING = "KET.Application";
    private static final int wdFormatPDF = 17;
    private static final int xlTypePDF = 0;
    private static final int ppSaveAsPDF = 32;

    private static String uploadFolder = ConfigKey.uploadFolder; //文件保存的目录

    public FileToPdf() {
    }

    public static void wordToPDF(String sfileName, String toFileName) {

        System.out.println("启动 Word...");
        long start = System.currentTimeMillis();
        ActiveXComponent app = null;
        Dispatch doc = null;
        try {
            app = new ActiveXComponent("Word.Application");
            app.setProperty("Visible", new Variant(false));
            Dispatch docs = app.getProperty("Documents").toDispatch();
            doc = Dispatch.call(docs, "Open", sfileName).toDispatch();
            System.out.println("打开文档..." + sfileName);
            System.out.println("转换文档到 PDF..." + toFileName);
            File tofile = new File(toFileName);
            if (tofile.exists()) {
                tofile.delete();
            }
            Dispatch.call(doc, "SaveAs", toFileName, // FileName
                    wdFormatPDF);
            long end = System.currentTimeMillis();
            System.out.println("转换完成..用时：" + (end - start) + "ms.");

        } catch (Exception e) {
            System.out.println("========Error:文档转换失败：" + e.getMessage());
        } finally {
            assert doc != null;
            Dispatch.call(doc, "Close", false);
            System.out.println("关闭文档");
            app.invoke("Quit", new Variant[]{});
        }
        // 如果没有这句话,winword.exe进程将不会关闭
        ComThread.Release();
    }

    /**
     * 文档转pdf
     *
     * @return boolean
     * @Param [srcFilePath, pdfFilePath, fileType]
     * @Author ywx
     * @Date 2020/10/10 16:07
     **/
    public static boolean fileToPdf(final String srcFilePath, final String pdfFilePath, final String fileType) throws Exception {
        final boolean[] rtn = {false};
        final String[] processName = {null};
        final ExecutorService exec = Executors.newFixedThreadPool(1);
        log.info("================> fileToPdf +fileType= "+fileType);
        Callable<String> call = new Callable<String>() {
            @Override
            public String call() throws Exception {
                //开始执行耗时操作
                switch (fileType) {
                    case "doc":
                    case "docx":
                    case "txt":
                        processName[0] = "wps.exe";
                        rtn[0] = wpsTopdf(srcFilePath, pdfFilePath);
                        break;
                    case "ppt":
                    case "pptx":
                        processName[0] = "wpp.exe";
                        rtn[0] = pptTopdf(srcFilePath, pdfFilePath);
                        break;
                    case "xls":
                    case "xlsx":
                        processName[0] = "et.exe";
                        rtn[0] = xlsTopdf(srcFilePath, pdfFilePath);
                        break;
                    default:
                        rtn[0] = true;
                        break;
                }
                return "执行完成!";
            }
        };
        try {
            Future<String> future = exec.submit(call);
            future.get(ConfigKey.timeout, TimeUnit.SECONDS); //任务处理超时时间
        } catch (TimeoutException ex) {
            log.error("转换处理超时" + ex.getMessage());
            killProc(processName[0]);
            throw new Exception("转换处理超时");
        }
        // 关闭线程池
        exec.shutdown();
        return rtn[0];
    }


    /**
     * @param srcFilePath 文档路径
     * @param pdfFilePath pdf路径
     * @return void
     * @throws Exception
     * @throws
     * @Description: 文档格式转换 支持 wps、wpt、doc、docx、dot、txt等所有文档格式文件
     * @author JornTang
     * @email 957707261@qq.com
     * @date 2017年9月14日
     */
    public static boolean wpsTopdf(String srcFilePath, String pdfFilePath) {
        log.info("================>wpsTopdf");
// wps com
        ActiveXComponent pptActiveXComponent = null;
        ActiveXComponent workbook = null;
// open thred
        ComThread.InitSTA();
        try {
            pptActiveXComponent = new ActiveXComponent(WORDSERVER_STRING);
            Variant[] openParams = {new Variant(srcFilePath),
                    new Variant(true), new Variant(true)};
            workbook = pptActiveXComponent.invokeGetComponent("Documents")
                    .invokeGetComponent("Open", openParams);
            workbook.invoke("SaveAs", new Variant(pdfFilePath),
                    new Variant(wdFormatPDF));
        } catch (Exception e) {
            log.error("文档转换pdf失败", e.getMessage());
            throw e;
        } finally {
            if (workbook != null) {
                workbook.invoke("Close");
                workbook.safeRelease();
            }
            if (pptActiveXComponent != null) {
                pptActiveXComponent.invoke("Quit");
                pptActiveXComponent.safeRelease();
            }
// close thred
            ComThread.Release();
        }
        return true;
    }


    /**
     * @param srcFilePath 幻灯片路径
     * @param pdfFilePath pdf路径
     * @return boolean
     * @throws
     * @Description: 幻灯片格式转换 支持ppt、pps、pptx、ppsx、dps、dpt、pot、uof
     * @author JornTang
     * @date 2017年9月14日
     */
    public static boolean pptTopdf(String srcFilePath, String pdfFilePath) throws Exception {
        ActiveXComponent pptActiveXComponent = null;
        ActiveXComponent workbook = null;
        boolean readonly = true;
        ComThread.InitSTA();
        try {
            pptActiveXComponent = new ActiveXComponent(PPTSERVER_STRING);
            workbook = pptActiveXComponent.invokeGetComponent("Presentations")
                    .invokeGetComponent(
                            "Open",
                            new Variant(uploadFolder + srcFilePath),
                            new Variant(readonly));
            workbook.invoke("SaveAs", new Variant(uploadFolder + pdfFilePath),
                    new Variant(ppSaveAsPDF));
            return true;
        } catch (Exception e) {
            log.error("ppt转pdf失败：" + e.getMessage());
            throw e;
        } finally {
            if (workbook != null) {
                workbook.invoke("Close");
                workbook.safeRelease();
            }
            if (pptActiveXComponent != null) {
                pptActiveXComponent.invoke("Quit");
                pptActiveXComponent.safeRelease();
            }
            ComThread.Release();
        }
    }

    /**
     * @param srcFilePath 幻灯片路径
     * @param pdfFilePath pdf路径
     * @return boolean
     * @throws
     * @Description: 表格格式转换 支持et、ett、xls、xlsx、xlt、uof、prn、csv
     * @author JornTang
     * @date 2017年9月14日
     */
    public static boolean xlsTopdf(String srcFilePath, String pdfFilePath) throws Exception {
        ActiveXComponent et = null;
        Dispatch workbook = null;
        ComThread.InitSTA();
        try {
            et = new ActiveXComponent(EXECLSERVER_STRING);
            et.setProperty("Visible", new Variant(false));
            Dispatch workbooks = et.getProperty("Workbooks").toDispatch();
            workbook = Dispatch.invoke(
                    workbooks,
                    "Open",
                    1,
                    new Object[]{(uploadFolder + srcFilePath), xlTypePDF,
                            Boolean.TRUE}, new int[1]).toDispatch();
            Dispatch.call(workbook, "ExportAsFixedFormat", xlTypePDF, (uploadFolder + pdfFilePath));
            Dispatch.invoke(workbook, "ExportAsFixedFormat", Dispatch.Method, new Object[]{new Variant(0), // PDF格式=0
                    (uploadFolder + pdfFilePath), new Variant(xlTypePDF) // 0=标准 (生成的PDF图片不会变模糊) 1=最小文件
                    // (生成的PDF图片糊的一塌糊涂)
            }, new int[1]);
            return true;
        } catch (Exception e) {
            log.error("excel转换pdf失败", e.getMessage());
            throw e;
        } finally {
            if (workbook != null) {
                Dispatch.call(workbook, "Close");
                workbook.safeRelease();
            }
            if (et != null) {
                et.invoke("Quit");
                et.safeRelease();
            }
            ComThread.Release();
        }

    }

    //杀死进程
    public static void killProc(String processName) {
        log.info("关闭应用程序：" + processName);
        //if (StringUtils.isNotBlank(processName)) {
        try {
            executeCmd("taskkill /F /IM " + processName);
            ComThread.Release();
        } catch (IOException e) {
            log.error("杀死进程失败", e.getMessage());
        }
        //}
    }

    //执行cmd命令
    public static String executeCmd(String command) throws IOException {
        log.info("Execute command : " + command);
        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("cmd /c " + command);
        BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
        String line = null;
        StringBuilder build = new StringBuilder();
        while ((line = br.readLine()) != null) {
            log.info(line);
            build.append(line);
        }
        return build.toString();
    }



    public static void main(String[] args) throws Exception {

        String s = "项目改造20211011V1.docx";
        String ss = "项目改造20211011V2.pdf";
        //wordToPDF(s,ss);
        fileToPdf(s, ss, "docx");
    }
}

